//定时器相关函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>

#include <sys/ioctl.h>
#include <arpa/inet.h>

#include "configure.h"
#include "macro.h"
#include "global.h"
#include "function.h"
#include "mysocket.h"
#include "mymemory.h"
#include "lock_mutex.h"

//设置踢出时钟
void MySocket::AddToTimerQueue(lpconnection_t connect) {
	MyMemory *memory = MyMemory::GetInstance();

	time_t future_time = time(NULL);
	future_time += wait_time_;

	Lock lock(&time_queue_mutex_);
	LPSTRUC_MSG_HEADER msg_header = (LPSTRUC_MSG_HEADER)memory->AllocMemory(msg_head_len_, false);
	msg_header->connect = connect;
	msg_header->current_sequence = connect->current_sequence;
	time_queue_map_.insert(std::make_pair(future_time, msg_header));
	current_size_++;
	timer_value_ = GetEarliestTime();
	return;
}

//从multmap中取出最早的时间返回
time_t MySocket::GetEarliestTime() {
	std::multimap<time_t, LPSTRUC_MSG_HEADER>::iterator pos;
	pos = time_queue_map_.begin();
	return pos->first;
}

//移除最早的时间
LPSTRUC_MSG_HEADER MySocket::RemoveFirstTimer() {
	std::multimap<time_t, LPSTRUC_MSG_HEADER>::iterator pos;
	LPSTRUC_MSG_HEADER tmp;
	if(current_size_ <= 0) {
		return NULL;
	}
	pos = time_queue_map_.begin();
	tmp = pos->second;
	time_queue_map_.erase(pos);
	--current_size_;
	return tmp;
}

//根据给的当前时间，找到时间超过的返回
LPSTRUC_MSG_HEADER MySocket::GetOverTimeTimer(time_t current_time) {
	MyMemory *memory = MyMemory::GetInstance();
	LPSTRUC_MSG_HEADER tmp;

	if(current_size_ == 0||time_queue_map_.empty()) {
		return NULL;
	}

	time_t earliest_time = GetEarliestTime();
	if(earliest_time <= current_time) {
		tmp = RemoveFirstTimer();
		if(if_timeout_kick_ != 1) {
			//不要求超时踢出
			time_t new_inqueue_time = current_time + wait_time_;
			LPSTRUC_MSG_HEADER tmp_msg_header = (LPSTRUC_MSG_HEADER)memory->AllocMemory(sizeof(STRUC_MSG_HEADER), false);
			tmp_msg_header->connect = tmp->connect;
			tmp_msg_header->current_sequence = tmp->current_sequence;

			time_queue_map_.insert(std::make_pair(new_inqueue_time, tmp_msg_header));
			current_size_++;
		}
		if(current_size_ > 0) {
			timer_value_ = GetEarliestTime();
		}
		return tmp;
	}
	return NULL;
}

//把指定用户tcp从timer表中踢出
void MySocket::DeleteFromTimerQueue(lpconnection_t connect) {
	std::multimap<time_t, LPSTRUC_MSG_HEADER>::iterator pos,pos_end;
	MyMemory *memory = MyMemory::GetInstance();

	Lock lock(&time_queue_mutex_);
lblMTQM:
	pos = time_queue_map_.begin();
	pos_end = time_queue_map_.end();
	for(;pos!=pos_end;++pos) {
		if(pos->second->connect == connect) {
			memory->FreeMemory(pos->second);
			time_queue_map_.erase(pos);
			--current_size_;
			goto lblMTQM;
		}
	}
	if(current_size_ > 0) {
		timer_value_ = GetEarliestTime();
	}
	return;
}

//清理时间队列中的内容
void MySocket::ClearAllFromTimerQueue() {
	std::multimap<time_t, LPSTRUC_MSG_HEADER>::iterator pos,pos_end;

	MyMemory *memory = MyMemory::GetInstance();

	pos = time_queue_map_.begin();
	pos_end = time_queue_map_.end();
	for(;pos!=pos_end; ++pos) {
		memory->FreeMemory(pos->second);
		--current_size_;
	}
	time_queue_map_.clear();
}

//时间队列监视和处理线程，将到期不发心跳包的用户踢出
void *MySocket::ServerTimerQueueMonitorThread(void *thread_data) {
	ThreadItem *thread = static_cast<ThreadItem*>(thread_data);

	MySocket* socket_obj = thread->this_;
	time_t absolute_time, current_time;
	int err;
	while(stop_event == 0) {
		if(socket_obj->current_size_ > 0) {
			absolute_time = socket_obj->timer_value_;
			current_time = time(NULL);
			if(absolute_time < current_time) {
				//时间到了，需要处理
				std::list<LPSTRUC_MSG_HEADER> idle_list_;//保存要处理的内容
				LPSTRUC_MSG_HEADER result;
				
				err = pthread_mutex_lock(&socket_obj->time_queue_mutex_);
				if(err != 0) {
					LogStderr(err, "MySocket::ServerTimerQueueMonitorThread()中pthread_mutex_lock()失败,返回错误码为%d.",err);
				}
				while((result = socket_obj->GetOverTimeTimer(current_time))!=NULL) {
					idle_list_.push_back(result);
				}
				err = pthread_mutex_unlock(&socket_obj->time_queue_mutex_);
				if(err != 0) {
					LogStderr(err, "MySocket::ServerTimerQueueMonitorThread()中pthread_mutex_unlock()失败,返回错误码为%d.",err);
				}
				LPSTRUC_MSG_HEADER tmp_msg;
				while(!idle_list_.empty()) {
					tmp_msg = idle_list_.front();
					idle_list_.pop_front();
					socket_obj->ProcPingTimeOutChecking(tmp_msg, current_time);
				}
			}
		}
		usleep(500 * 1000);
	}
	return (void*)0;
}

//心跳包检测时间到，子类实现具体动作
void MySocket::ProcPingTimeOutChecking(LPSTRUC_MSG_HEADER tmp_msg, time_t current_time) {
	MyMemory *memory = MyMemory::GetInstance();
	memory->FreeMemory(tmp_msg);
}




